using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Security.Claims;
using System.Text;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using backend.Models;

namespace Services
{
    public class JwtHelper
    {
        private static readonly IConfiguration Configuration;
        private static readonly JwtSettings jwtSettings;

        static JwtHelper() {
            Configuration = new ConfigurationBuilder()
                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                .AddEnvironmentVariables()
                .Build();
            jwtSettings = new JwtSettings();
            Configuration.GetRequiredSection("Jwt").Bind(jwtSettings);
        }

        public static string? GetTokenFromHeader(HttpRequest request) {
            string authHeader = request.Headers["Authorization"].ToString();

            // 检查Authorization头是否以"Bearer "开头
            if (authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
            {
                // 移除"Bearer "前缀，返回纯令牌
                return authHeader.Substring("Bearer ".Length).Trim();
            }

            // 如果没有找到有效的JWT令牌，返回null
            return null;
        }

        
        public static string GenerateJwtToken(string userId, string role)
        {
            var tokenHandler = new JwtSecurityTokenHandler();
            var key = Encoding.ASCII.GetBytes(jwtSettings.Key);

            var tokenDescriptor = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(new Claim[]
                {
                    new Claim(ClaimTypes.Name, userId),
                    new Claim(ClaimTypes.Role, role)
                }),
                Expires = DateTime.UtcNow.AddDays(7),
                SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
            };

            var token = tokenHandler.CreateToken(tokenDescriptor);
            return tokenHandler.WriteToken(token);
        }

        public static CustomizedJwtPayload? ValidateJwtToken(string token)
        {
            var tokenHandler = new JwtSecurityTokenHandler();
            var key = Encoding.ASCII.GetBytes(jwtSettings.Key);

            try
            {
                var tokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(key),
                    ValidateIssuer = false, // 不验证发行者
                    ValidateAudience = false, // 不验证受众
                    // 如果期望使用不同的时区，则可以设置 ClockSkew
                    ClockSkew = TimeSpan.Zero
                };

                var principal = tokenHandler.ValidateToken(token, tokenValidationParameters, out SecurityToken securityToken);
                var jwtSecurityToken = securityToken as JwtSecurityToken;
                if (jwtSecurityToken == null || !jwtSecurityToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256, StringComparison.InvariantCultureIgnoreCase))
                {
                    throw new SecurityTokenException("Invalid token");
                }
                var parsedUserId = principal.FindFirst(ClaimTypes.Name)?.Value;
                // Console.WriteLine("parsedUserId: " + parsedUserId);
                var parsedRole = principal.FindFirst(ClaimTypes.Role)?.Value;
                // Console.WriteLine("parsedRole: " +  parsedRole);
                if (parsedUserId == null || parsedRole == null)
                {
                    throw new SecurityTokenException("Invalid token");
                }
                return new CustomizedJwtPayload { UserId = parsedUserId, Role = parsedRole };
            }
            catch 
            {
                // 如果出现任何错误，返回null或抛出异常
                return null;
            }
        }

        public static CustomizedJwtPayload? GetAndValidateJwtToken(HttpRequest request)
        {
            var token = GetTokenFromHeader(request);
            if (token == null)
            {
                return null;
            }
            return ValidateJwtToken(token);
        }
    }
}